/*  

Cafechess Library: Cover basic chess programming needs, like GUI, Engine integration, 
FEN and PGN parsing.

                 \\|//
                 (o o)
--------------ooO-(_)-Ooo----------------------------------
Copyright (C) 2009  By Gregory A. Prentice Snoqualmie, WA
                    www.cafechess.org
                    cafechess@comcast.net
                      Oooo
--------------oooO----(  )---------------------------------
              (  )    (_/
               \_)

Microsoft Public License (Ms-PL)
               
Revisions:

Author        Date    Description:

*/
using System;
using System.Collections.Generic;
using System.Text;


namespace Cafechess.Text
{
  /// <summary>
  /// Provides us with some additional string manipulation functions that are not
  /// available in the StringBuilder class.  Features are:
  ///   1) Allows the treatment of a string as a flat file record, 
  ///   reading and writing to embedded fields.
  /// </summary>
  public class ExtendedStringBuilder
  {
    /// <summary>
    /// Defines any specific data padding as we insert our data.
    /// </summary>
    //public enum PADDING { None, Left, Right, Center };

    /// <summary>
    /// Since we can't derive from this class we just make it a public member so everyone
    /// can access it.
    /// </summary>
    public StringBuilder StringBuilder
    {
      get { return coStringBuilder; }
    }
    StringBuilder coStringBuilder;
    /// <summary>
    /// Private member.
    /// </summary>
    private bool coAutoExpand;
    /// <summary>
    /// If true we will automatically append enough fill charaters if we would
    /// otherwise overrun our StringBuilder.
    /// </summary>
    public bool IsAutoExpand
    {
      get { return coAutoExpand; }
      set { coAutoExpand = value; }
    }

    private char coFillCharacter;
    /// <summary>
    /// Used to fill the empty area of our buffer.
    /// </summary>
    public char FillCharacter
    {
      get { return coFillCharacter; }
      set { coFillCharacter = value; }
    }

    /// <summary>
    /// Always require that we start with some initial capacity.
    /// </summary>
    /// <param name="capacity"></param>
    public ExtendedStringBuilder(int capacity)
    {
      coFillCharacter = ' ';
      Initialize(capacity);
    }
    /// <summary>
    /// Defines the initial capacity and also set the array to our fill charater.
    /// </summary>
    /// <param name="capacity"></param>
    /// <param name="fill"></param>
    public ExtendedStringBuilder(int capacity, char fill)
    {
      coFillCharacter = fill;
      Initialize(capacity);
    }
    /// <summary>
    /// Takes a string as our initial value to setup our buffer.
    /// </summary>
    /// <param name="data"></param>
    public ExtendedStringBuilder(string data)
    {
      coFillCharacter = ' ';
      Initialize(0);
    }
    /// <summary>
    /// Default initialization code.
    /// </summary>
    /// <param name="capacity"></param>
    private void Initialize(int capacity)
    {
      coStringBuilder = new StringBuilder(capacity);
      if( capacity > 0 )
        coStringBuilder.Append(coFillCharacter, capacity);
      coAutoExpand = true;
    }
    
    /// <summary>
    /// Puts the data string into our string buffer at a specified location and
    /// maximum width.
    /// </summary>
    /// <param name="data"></param>
    /// <param name="start"></param>
    /// <param name="width"></param>
    /// <returns></returns>
    public bool Put(string data, int start, int width)
    {
      bool copy=false,ok = false;
      if (data.Length > 0)
      {
        if (coStringBuilder.Length >= start + width)
        {
          copy = true;
        }
        else if (coAutoExpand == true)
        {
          int grow = (start + width) - coStringBuilder.Length;
          coStringBuilder.Append(coFillCharacter, grow);
          copy = true;
        }
        if(copy == true )
        {
          if (data.Length < width)
          {
            width = data.Length;
          }
          width--;
          start += width;
          while (width >= 0)
          {
            coStringBuilder[start] = data[width];
            start--;
            width--;
          }
          ok = true;
        }
      }
      return ok;
    }

    /// <summary>
    /// Return a value from a specific offset in our string and of a specific length.
    /// </summary>
    /// <param name="start"></param>
    /// <param name="width"></param>
    /// <returns></returns>
    public string Get(int start, int width)
    {
      char[] buffer = new char[width];
      if (coStringBuilder.Length >= start + width)
      {
        coStringBuilder.CopyTo(start, buffer, 0, width);        
      }
      return new string(buffer).Trim();
    }
    /// <summary>
    /// Resets our buffer to a clean filled state.
    /// </summary>
    public void Reset()
    {
      int length = coStringBuilder.Length;
      coStringBuilder.Length = 0;
      coStringBuilder.Append(coFillCharacter,length);
    }
    /// <summary>
    /// Resets our buffer with our new data record.
    /// </summary>
    /// <param name="data"></param>
    public void Reset(string data)
    {
      coStringBuilder.Length = 0;
      coStringBuilder.Append(data);
    }
  }
}
